package com.jmxcfc.blfsc.ssq.service.contract.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jmxcfc.blfsc.common.common.enums.ProcessStateEnum;
import com.jmxcfc.blfsc.common.common.request.BaseRequest;
import com.jmxcfc.blfsc.common.common.response.BaseResponse;
import com.jmxcfc.blfsc.common.exception.AfterOutboundException;
import com.jmxcfc.blfsc.common.exception.BeforeOutboundException;
import com.jmxcfc.blfsc.common.exception.OutboundException;
import com.jmxcfc.blfsc.common.sign.SignRequest;
import com.jmxcfc.blfsc.common.sms.BaseContext;
import com.jmxcfc.blfsc.common.validation.rule.RequestFieldRule;
import com.jmxcfc.blfsc.common.validation.rule.SignRulesUtil;
import com.jmxcfc.blfsc.ssq.common.Constants;
import com.jmxcfc.blfsc.ssq.entity.LockContractSub;
import com.jmxcfc.blfsc.ssq.modle.response.SsqResponse;
import com.jmxcfc.blfsc.ssq.service.SignatureService;
import com.jmxcfc.blfsc.ssq.service.contract.ILockContractRequestService;
import com.jmxcfc.blfsc.ssq.service.contract.ILockContractSubService;
import com.jmxcfc.blfsc.ssq.service.contract.ISignContractSubService;
import com.jmxcfc.blfsc.ssq.service.contract.IUploadContractSubService;
import com.jmxcfc.blfsc.ssq.util.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.util.List;

/**
 * 功能描述
 *
 * @author: pbs
 * @date: 2024年09月04日 0:17
 */
@Service
@Slf4j
public class LockContractRequestServiceImpl implements ILockContractRequestService {


    @Value("${com.ssq.lockedContractUrl}")
    private String lockedContractUrl;




    private SignatureService signatureService;

    private ILockContractSubService lockContractSubService;
    private IUploadContractSubService uploadContractSubService;
    private ISignContractSubService signContractSubService;



    private RestTemplate restTemplate;

    @Autowired
    public void setSignatureService(SignatureService signatureService) {
        this.signatureService = signatureService;
    }

    @Autowired
    public void setLockContractSubService(ILockContractSubService lockContractSubService) {
        this.lockContractSubService = lockContractSubService;
    }

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Autowired
    public void setUploadContractSubService(IUploadContractSubService uploadContractSubService) {
        this.uploadContractSubService = uploadContractSubService;
    }

    @Autowired
    public void setSignContractSubService(ISignContractSubService signContractSubService) {
        this.signContractSubService = signContractSubService;
    }


    @Override
    public BaseResponse<LockContractSub> sendRequest(BaseRequest<SignRequest<String>> requestMessage) {

        BaseContext<String> baseContext = new BaseContext<>();
        //头部参数校验规则:业务号
        List<RequestFieldRule<?>> headerElementRules = baseContext.getHeaderElementRules();
        headerElementRules.add(SignRulesUtil.getRequestNoRule());
        
        return execute(requestMessage, baseContext);
    }

    /**
     * 1、规则校验:业务号
     * todo 待确认
     * 2、参数 合同id:取值于签署合同（即自动签）接口表 SSQ_SIGN_CONTRACT_SUB 的值最新且签署成功的记录
     * @param request
     * @param response
     * @param baseContext
     * @throws BeforeOutboundException
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void beforeOutbound(BaseRequest<SignRequest<String>> request, BaseResponse<LockContractSub> response, BaseContext<String> baseContext) throws BeforeOutboundException {
        String requestNo = request.getHeader().getRequestNo();
        try {
            log.info("请求业务号requestNo:{},锁定并结束合同接口,前置处理:数据落库和参数组装", requestNo);
            LockContractSub lockContractSub = new LockContractSub();
            lockContractSub.setRequestNo(requestNo);

            //参数组织、regUserPersonalSub设置值
            String requestParamStr = buildParam(request, lockContractSub);
            //由于是签名参数追加为url参数:/openapi/v2/storage/contract/lock/?developerId=aaaaaa&rtick=14840209310001&signType=rsa
            String urlPathParams = signatureService.buildUrlPathParams(lockedContractUrl, "", requestParamStr);
            //请求路径的url的参数
            baseContext.setExtendStr(urlPathParams);
            //设置请求
            baseContext.setRestHttpEntity(HttpUtils.creatRequestEntity(requestParamStr));
            //保存数据
            lockContractSubService.save(lockContractSub);
            //主键
            baseContext.setRecordId(lockContractSub.getId());
            log.info("请求业务号requestNo:{},锁定并结束合同接口,前置处理结束", requestNo);
        } catch (Exception e) {
            log.error("请求业务号requestNo:{},前置处理异常:{}", requestNo, e.getMessage(), e);
            throw new BeforeOutboundException(e.getMessage(), e);
        }
    }

    @Override
    public void outbound(BaseRequest<SignRequest<String>> request, BaseResponse<LockContractSub> response, BaseContext<String> baseContext) throws OutboundException {
        try{
            //请求url的,必须要用URL,否则restTemplate会对url进行
            URI requestUrl = new URI( StringUtils.join(lockedContractUrl, baseContext.getExtendStr()));
            log.info("请求业务号requestNo:{},锁定并结束合同接口,发送请求外呼,请求地址:{},请参数:{}",request.getHeader().getRequestNo(),requestUrl,baseContext.getRestHttpEntity().getBody());
            String resp = restTemplate.postForObject(requestUrl, baseContext.getRestHttpEntity(), String.class);
            log.info("请求业务号requestNo:{},锁定并结束合同接口,发送请求外呼,响应内容:{}", request.getHeader().getRequestNo(), resp);
            baseContext.setRestResponse(resp);
        } catch (Exception e) {
            log.error("请求业务号requestNo:{},锁定并结束合同接口,发送请求外呼异常:{}", request.getHeader().getRequestNo(), e.getMessage());
            throw new OutboundException(e.getMessage(), e);
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void afterOutbound(BaseRequest<SignRequest<String>> request, BaseResponse<LockContractSub> response, BaseContext<String> baseContext) throws AfterOutboundException {
        String requestNo = request.getHeader().getRequestNo();
        try{
            log.info("请求业务号requestNo:{},锁定并结束合同接口,后置处理:解析响应结果", requestNo);
            LockContractSub lockContractSub = new LockContractSub();
            lockContractSub.setRequestNo(requestNo);
            //注意这边是根据主键更新
            lockContractSub.setId(baseContext.getRecordId());

            SsqResponse ssqResponse = JSON.parseObject(baseContext.getRestResponse(),SsqResponse.class);
            //错误码值,0:成功
            String errno = ssqResponse.getErrno();
            //错误信息描述
            String errmsg = ssqResponse.getErrmsg();
            log.info("请求业务号requestNo:{},锁定并结束合同接口,响应的结果 errno:{},errmsg:{}", requestNo, errno, errmsg);
            if (StringUtils.equals(errno, Constants.ERRNO_0)) {
                response.getHeader().setProcessState(ProcessStateEnum.SUCCESS);
            }else {
                response.getHeader().setProcessState(ProcessStateEnum.FAILURE);
            }
            lockContractSub.setErrno(errno);
            lockContractSub.setErrmsg(errmsg);
            lockContractSubService.updateById(lockContractSub);
            response.getHeader().setResCode(errno);
            response.getHeader().setResMessage(errmsg);
            response.setBody(lockContractSub);
            log.info("请求业务号requestNo:{},锁定并结束合同接口接口,后置处理结束", requestNo);
        } catch (Exception e) {
            log.error("请求业务号requestNo:{},锁定并结束合同接口接口,后置处理异常:{}", requestNo, e.getMessage(), e);
            throw new AfterOutboundException(e.getMessage(), e);
        }
    }



    private String buildParam(BaseRequest<SignRequest<String>> request, LockContractSub lockContractSub) {
        JSONObject requestParam = new JSONObject();
        String requestNo = request.getHeader().getRequestNo();
        //String contractId = uploadContractSubService.queryLatestContractId(requestNo);
        String contractId = signContractSubService.queryLatestContractId(requestNo);
        log.info("根据请求业务号requestNo:{},参数组织,【锁定并结束合同接口】查询表SSQ_SIGN_CONTRACT_SUB的合同id(contractId):{}", requestNo, contractId);
        if (StringUtils.isBlank(contractId)) {
            log.error("根据请求业务号requestNo:{},查询表SSQ_UPLOAD_CONTRACT_SUB的合同id,查询结果为空",requestNo);
            throw new BeforeOutboundException("未查询到合同id");
        }
        requestParam.put(Constants.CONTRACT_ID, contractId);
        lockContractSub.setContractId(contractId);
        log.info("请求业务号requestNo:{},参数组织完成,参数:{}", request.getHeader().getRequestNo(), JSON.toJSONString(requestParam));
        return JSON.toJSONString(requestParam);
    }


}